package AEF::AEFReader;

use Moose;
use Modern::Perl;
use Log::Log4perl qw( :easy );
require AEF::Module;
require AEF::Entity;

my $aefHeader = "vV";

has 'ptr' => (is => 'rw', isa => 'Int');
has 'data' => (is => 'rw', isa => 'Str');
has 'processor' => (is => 'rw', isa => 'AEF::AEFProcessor');
has mustBeAEF  => (is => 'rw', isa => 'Bool', default => 0);

my $header_length = 6;
my $header_format = 'vV';


sub CheckHeader
{
	my $self = shift;
	my $header = substr($self->data, 0, $header_length);
	my ($type, $length) = unpack($header_format, $header);
	die "Unexpected file format" if($type != 1);
	die "Unexpected file format" if($self->mustBeAEF && $length != 32);
	my $chunk = substr($self->data, $header_length, 2);
	my ($version) = unpack("v", $chunk);
	die "Unexpected AEF version" if $version != 0x280;
}

sub ReadAEF
{
	my $self = shift;
	my $data = shift;

	$self->data($data);
	$self->ptr(0);
	$self->CheckHeader();

	$self->ReadBlocks($self->ptr);
}

sub ReadBlocks
{
	my $self = shift;
	my $ptr = shift;
    my $processor = shift;
    $self->processor($processor) if $processor;
	my $data = $self->data;

	$self->ptr($ptr);
	my $logger = get_logger();

	while($self->ptr < length($data))
	{
		my $header = substr($data, $self->ptr, $header_length);
		my ($type, $length) = unpack($header_format, $header);
		if($self->processor->RequireDataForType($type))
		{
			my $data_chunk = substr($data, $self->ptr + $header_length, $length);
			my $unpack_string = $self->processor->TypeMap($type);
			my $decoded;
			if($unpack_string)
			{
				my @data = unpack($unpack_string, $data_chunk);
				my $length = @data;
				if($length == 1)
				{
					$decoded = $data[0];
				} 
				else
				{
					$decoded = \@data;
				}
			}
			else
			{
				$decoded = $data_chunk;
			}
			$self->processor->ProcessBlock($type, $decoded, $self->ptr, $length);
		}
		if($self->processor->doneProcessing)
		{
			last;
		}
		$self->ptr($length + $header_length + $self->ptr);
        # return the processor as well to make map 
        # operations easier.
	}
    return $processor; 
}


1;

no Moose;

